﻿using Lan.Infrastructure.CameraOnvif;
using Lan.ServiceCore.Onvif;
using Lan.ServiceCore.Services;
using Lan.ServiceCore.WebScoket;
using Model;
using System.Collections.Concurrent;
using System.Diagnostics;
using System.Drawing;

namespace Lan.ServiceCore.TargetCollection
{
    /// <summary>
    /// 防区
    /// </summary>
    public class WDefenceArea : IDisposable 
    {
        #region 成员变量
        AlarmService alarmService = new AlarmService();
        ONVIF_COMMON_INFO common = new ONVIF_COMMON_INFO();

        List<OnvifManage_COMMON_INFO> list_common = new List<OnvifManage_COMMON_INFO>();


        /// <summary>
        /// 绘制区域相对防区的坐标
        /// </summary>
        public List<PointF[]> ListRadarPolygon;

        const int TrackInterval = 200;

        int _nID;
        string _name;
        int _nGroupId;
        bool _bAlgorithmEnable;
        bool _bDefenceEnable;
        bool _IsRunFormWvfMain = true;
        PointF _ptPosition;
        int _nDefenceRadius;
        bool _bOnline;
        bool _bInitialized;
        bool _bIsAlarmInHand;
        //object _lockTargets;
        WCamera _camera;
        List<WRadar> _radars;
        List<WCamera> _cameras;

        TargetCollection _targetList;           //防区轨迹列表
        //int _targetId = 0;                      //在一个防区内，报警目标的唯一标志，非负整数
        //RadarDataFilterLib.RadarDataFilter _radarTargetFilter = null;
        Stopwatch _watchAlarmHandle;

        bool _bTaskContinue;                    //目标跟踪线程允许允许标志

        int _noControlTimesForStopCamera;       //连续多少次循环中没有控制球机后，需要定位球机到最后一次控制位置
        int _cameraSwitchTimespan;				//目标切换等待的时间，在此时段内使用广角显示


        TargetPath _currentTarget;              //当前跟踪目标
        TargetPath _lastTarget;                 //上次跟踪的目标
        DateTime _trackTime;                    //目标跟踪起始时间
        DateTime _cameraSwitchTargetEndTime;    //目标切换等待的结束时间，在此时间内不执行球机控制
        DateTime _lastManualControlTime;        //用户最后一次手动控制球机的时间
        int _stateManualControl = 0;

        /// <summary>
        /// 定时器方案id
        /// </summary>
        private int _timerSchemeId;


        private RBTrackSdk.TrackCallBack _TrackCallBack;


        #endregion

        #region 属性

        #region 报警
        public bool IsRunFormWvfMain
        {
            get { return _IsRunFormWvfMain; }
            set { _IsRunFormWvfMain = value; }
        }
        public List<TargetPath> TargetList
        {
            get { return _targetList.TargetList; }
            set { _targetList.TargetList = value; }
        }

        public Lan.ServiceCore.AlarmRecord.AlarmRecord Alarm
        {
            set;
            get;
        }
        public DateTime AlarmBeginTime { get; set; }

        #endregion
        public int ScenarioID;

        /// <summary>
        /// 防区IP（为了适应旧版本的一些功能，实际上是ID的字符串）
        /// </summary>
        public string Ip { get { return _nID.ToString(); } }

        public int ID
        {
            get { return _nID; }
            internal set { _nID = value; }
        }

        /// <summary>
        /// 预览窗口是否关闭
        /// </summary>
        public bool CloseFormHoverVideo
        {
            get;
            set;
        }
        public string Name
        {
            get { return _name; }
            set { _name = value; }
        }

        public string VideoName
        {
            get;
            set;
        }


        public bool DefenceEnable
        {
            get
            {
                return _bDefenceEnable;
            }
            set
            {
                _bDefenceEnable = value;
                if (false == value)
                {
                    this.Alarm = null;
                }
            }
        }

        /// <summary>
        /// 防区图标在电子地图上的位置，用百分比表示，取值0~1.0
        /// </summary>
        public PointF Position
        {
            get { return _ptPosition; }
            internal set { _ptPosition = value; }
        }

        public int DefenceRadius
        {
            get { return _nDefenceRadius; }
            internal set { _nDefenceRadius = value; }
        }

        public bool Online
        {
            get { return _bOnline; }
            internal set { _bOnline = value; }
        }

        public bool Initialized
        {
            get { return _bInitialized; }
            internal set { _bInitialized = value; }
        }

        public WCamera Camera
        {
            get { return _camera; }
            internal set { _camera = value; }
        }
        public List<WCamera> Cameras
        {
            get { return _cameras; }
            internal set { _cameras = value; }
        }

        public List<WRadar> Radars
        {
            get { return _radars; }
            internal set { _radars = value; }
        }

        public List<int> TargetIdSelected
        {
            get { return _targetList.TargetIdSelected; }
            set { _targetList.TargetIdSelected = value; }
        }

        internal object TargetSyncLock { get; set; }

        public int TimerSchemeId
        {
            get { return _timerSchemeId; }
            set { _timerSchemeId = value; }
        }

        /// <summary>
        /// 是否报警处理中
        /// </summary>
        public bool IsAlarmInHand
        {
            set
            {
                if (_bIsAlarmInHand != value)
                {
                    if (value == false && _camera != null)
                    {
                        VideoName = _camera.c_filename;
                        if ((DateTime.Now - AlarmBeginTime) <= TimeSpan.FromSeconds(5))
                        {
                            int maxID = alarmService.GetInfo(ID, "Not handled"); // db.Queryable<AlarmModel>().Where(it => it.AreaId == ID && it.DealWith == "Not handled").Max(it => it.Id);
                            if (maxID > 0)
                            {
                                alarmService.DeleteAlarm(maxID);
                            }
                        }
                        _camera.StopSaveFile(_cameras);
                        Alarm = null;

                    }
                    _bIsAlarmInHand = value;

                    if (value)
                    {
                        Alarming = true;
                    }
                }
            }
            get { return _bIsAlarmInHand; }
        }

        public bool Alarming { get; set; }

        #endregion

        #region 构造函数
        public void RadarDefenceEnable()
        {
            foreach (WRadar _r in _radars)
            {
                _r.DefenceEnable = _bDefenceEnable;
            }
        }

        public WDefenceArea()
        {
            _lastTarget = null;
            //_maxFilter = new MaxFilter();
            _lastManualControlTime = _cameraSwitchTargetEndTime = _trackTime = DateTime.Now;

            Alarming = false;
            TargetSyncLock = new object();

            _targetList = new TargetCollection(this);

            _watchAlarmHandle = new Stopwatch();
            CloseFormHoverVideo = true;
            _bTaskContinue = true;
            Task.Factory.StartNew(trackThread).ContinueWith(t => Console.WriteLine("防区球机控制线程发生错误\r\n"
                            + t.Exception.InnerException.ToString()),
                        TaskContinuationOptions.OnlyOnFaulted);
            ListRadarPolygon = new List<PointF[]>();

        }

        internal WDefenceArea(DefenceareaModel defencearea)
            : this()
        {
            _nID = defencearea.Id;
            _name = defencearea.Name;

            _bDefenceEnable = defencearea.DefenceEnable == 1 ? true : false;
            float x = 0, y = 0;

            _ptPosition = new PointF(x, y);
            _nDefenceRadius = defencearea.DefenceRadius;


            WCamera[] cameras = CameraManager.GetInstance().GetBindingCameraOfDefenceArea(_nID);
            if (cameras.Length > 0)
            {
                _camera = cameras[0];

                _cameras = new List<WCamera>(cameras);
            }

            //WRadar[] radars = RadarManager.GetInstance().GetBindingRadarOfDefenceArea(_nID);
            //_radars = new List<WRadar>(radars);

            _bOnline = false;
            _bInitialized = true;
            //_MainRadar = defencearea.MainRadar;

            //RadarDefenceEnable();
        }

        internal WDefenceArea(string name, int nGroupId, bool bAlgorithmEnable, bool bDefenceEnable, PointF ptPosition, int nDefenceRadius)
            : this()
        {
            _name = name;
            _nGroupId = nGroupId;
            _bAlgorithmEnable = bAlgorithmEnable;
            _bDefenceEnable = bDefenceEnable;
            _ptPosition = ptPosition;
            _nDefenceRadius = nDefenceRadius;
            _bOnline = false;
            _bInitialized = true;
            _radars = new List<WRadar>(0);
            _cameras = new List<WCamera>(0);
            _camera = null;
            //SaveToDatabase();

        }

        public void Dispose()
        {
            _bTaskContinue = false;
            if (_camera != null)
            {
                _camera.Dispose();
                _camera = null;
            }
        }

        #endregion

        #region 防区操作

        public PointF ConvertPoint(float[] sz)
        {
            double rad = sz[0] * Math.PI / 180.0;
            double x = sz[1] * Math.Sin(rad);
            double y = sz[1] * Math.Cos(rad);
            return new PointF((float)x, (float)y);
        }

        private void RefreshOnlineState()
        {
            bool online = false;
            foreach (WRadar radar in _radars)
            {
                if (radar.Online && radar.Enable)
                {
                    online = true;
                    break;
                }
            }
            Online = online;
        }

        public bool RadarAlarmOvertime()
        {
            double span = _watchAlarmHandle.ElapsedMilliseconds / 1000;
            if (span > 5)
                return true;
            else
                return false;
        }

        public bool AlarmVideoOvertime(DateTime now)
        {
            int maxAlarmTime = 10;
            if (maxAlarmTime > 0 && (now - AlarmBeginTime).TotalSeconds > maxAlarmTime)
                return true;
            else
                return false;
        }

        public void UpdateAlarmTime()
        {
            _watchAlarmHandle.Restart();
        }

        internal void ExecuteAlarmData()
        {
            try
            {
                if (Alarm != null)
                    return;

                Lan.ServiceCore.AlarmRecord.AlarmRecord ar = new Lan.ServiceCore.AlarmRecord.AlarmRecord();
                ar.AreaId = _nID;                        //防区IP         
                ar.Name = Name;                    //防区名
                ar.Time = DateTime.Now;
                if (_camera != null)
                {
                    ar.WCameraIp = _camera.Ip;
                }

                List<string> videoname = new List<string>();
                WCamera[] cameras = CameraManager.GetInstance().GetBindingCameraOfDefenceArea(_nID);
                if (cameras.Length > 0)
                {
                    for (int i = 0; i < cameras.Length; i++)
                    {
                        string name = ar.CreateVideoName(cameras[i].Ip);
                        videoname.Add(name);//生成视频文件名
                    }
                }
                ar.VideoName = videoname;
                this.Alarm = ar;
            }
            catch (Exception ex)
            {
                //Log.Error(ex.ToString());
            }
        }

        #endregion

        #region 目标列表和目标跟踪


        internal void ClearTargets()
        {
            lock (this.TargetSyncLock)
            {
                _targetList.ClearTargets();
            }

        }

        internal void CheckPathOvertime()
        {
            _targetList.CheckPathOvertime();
        }
        internal void CheckPathOvertimeAlarm()
        {
            if (Alarm != null)
            {
                _targetList.CheckPathOvertimeAlarm(AlarmBeginTime);
            }
        }

        internal void ClearLostTargets()
        {
            _targetList.ClearLostTargets();
        }

        /// <summary>
        /// 添加雷达的报警信息到队列
        /// </summary>
        /// <param name="radar"></param>
        /// <returns>是否成功添加了目标</returns>
        internal bool AddAlarmTarget(WRadar radar)
        {
            return _targetList.AddTarget(radar);
        }
        int newAvailableCount = 1;
        int cameraNoControlCount = 0;
        bool _bPtrsControlTour = true;//没有回到巡视点


        List<RBTRACK_Info> _list_RBTRACK = new List<RBTRACK_Info>();

        ConcurrentDictionary<string, isRBTRACK_Info> isTRACK = new ConcurrentDictionary<string, isRBTRACK_Info>();
        public class isRBTRACK_Info
        {
            public string RadarIp { get; set; }
            public string CameraIp { get; set; }
        }

        List<TargetPath> _targetPathListNew = new List<TargetPath>();       //防区当前报警目标列表

        public void trackTargetPath()
        {
            if (_targetList.TargetList.Count > 0)
            {
                //if (!TargetCommon.TrackStatus)
                //{
                //    return;
                //}

                _bPtrsControlTour = true;

                //撤防状态不执行
                if (!_bDefenceEnable)
                {
                    return;
                }
                _targetPathListNew = _targetList.TargetList;

                _list_RBTRACK = RBTRACKManage.list_RBTRACK;

                int channelId = -1;

                WCamera[] cameras = CameraManager.GetInstance().GetBindingCameraOfDefenceArea(_nID);

                if (_targetPathListNew.Count > 0)
                {
                    RADAR_TARGETS_T[] list_RADAR_TARGETS_T = new RADAR_TARGETS_T[_targetPathListNew.Count];
                    for (int i = 0; i < _targetPathListNew.Count; i++)
                    {
                        string radarip = _targetPathListNew[i].RadarIP;
                        string mainradarip = _targetPathListNew[i].MainRadarIP;

                        RADAR_TARGETS_T _RADAR_TARGETS_T = new RADAR_TARGETS_T();

                        _RADAR_TARGETS_T.targetId = _targetPathListNew[i].TargetId;                     //目标ID范围0x01~0x40
                        _RADAR_TARGETS_T.type = _targetPathListNew[i].TargetType;                //目标类型
                        _RADAR_TARGETS_T.speed_X = _targetPathListNew[i].SpeedX;                      //X方向速度
                        _RADAR_TARGETS_T.speed_Y = _targetPathListNew[i].SpeedY;                      //Y方向速度

                        _RADAR_TARGETS_T.cod_X = _targetPathListNew[i].AxesX;
                        _RADAR_TARGETS_T.cod_Y = _targetPathListNew[i].AxesY;

                        _RADAR_TARGETS_T.distance = _targetPathListNew[i].Distance;                     //目标距离
                        _RADAR_TARGETS_T.azimuth = _targetPathListNew[i].AzimuthAngle;                      //目标方位角


                        list_RADAR_TARGETS_T[0] = _RADAR_TARGETS_T;

                        cameraNoControlCount = 0;
                    }

                    if (cameras.Length > 0)
                    {
                        if (_list_RBTRACK.Count > 0)
                        {
                            for (int j = 0; j < _list_RBTRACK.Count; j++)
                            {
                                if (_list_RBTRACK[j].CameraIp == Camera.Ip && _list_RBTRACK[j].DefenceareaId == _nID.ToString() && _list_RBTRACK[j].channelId != -1)
                                {
                                    channelId = _list_RBTRACK[j].channelId;

                                    int s = RBTrackSdk.RBTRACK_UpdateTargets(channelId, list_RADAR_TARGETS_T, list_RADAR_TARGETS_T.Length);

                                }
                            }
                        }
                    }
                }
            }
            else
            {
                // Log.Debug("巡视点3:");
                PtrsControlTour();
            }
        }

        public void DeleteTrack()
        {
            //不跟了，退出
            int mchannelId = 0;
            RBTrackSdk.RBTRACK_DeleteTrack(mchannelId);
            RBTrackSdk.RBTRACK_DeInit();
        }
        private int TrackCallBack(int channelId, int targetId, IntPtr userPtr)
        {

            try
            {

            }
            catch
            {
            }
            return 0;
        }

        public void PtrsControlTour()
        {
            try
            {
                //Log.Debug("巡视点执行1");
                if (Camera != null)
                {
                    //Log.Debug("巡视点执行2");
                    cameraNoControlCount++;
                    if ((_noControlTimesForStopCamera < cameraNoControlCount && _bPtrsControlTour) || _noControlTimesForStopCamera * 5 < cameraNoControlCount)
                    {
                        //Log.Debug("巡视点执行3");
                        cameraNoControlCount = 0;

                        if (Camera.InspectionID != null)
                        {
                            list_common = OnvifManage._common;

                            for (int i = 0; i < list_common.Count; i++)
                            {
                                // Log.Debug("巡视点执行3.1");
                                if (list_common[i].ip.Contains(Camera.Ip))
                                {
                                    common = list_common[i].COMMON_INFO;
                                    // Log.Debug("巡视点执行3.2");
                                }
                            }

                            byte[] rtspUrl = new byte[64];
                            rtspUrl = System.Text.Encoding.UTF8.GetBytes(Camera.InspectionID); ;
                            // Log.Debug("巡视点执行3.4 rtspUrl :" + rtspUrl.Length.ToString());

                            if (rtspUrl.Length > 0)
                            {
                                ONVIF_PTZ_GOTOPRESET _ONVIF_PTZ_GOTOPRESET = new ONVIF_PTZ_GOTOPRESET();
                                _ONVIF_PTZ_GOTOPRESET.presetId = rtspUrl;
                                _ONVIF_PTZ_GOTOPRESET.panSpeed = 0.5f;
                                _ONVIF_PTZ_GOTOPRESET.tiltSpeed = 0.1f;
                                _ONVIF_PTZ_GOTOPRESET.zoomSpeed = 0.1f;

                                int ret = onvifsdk.ONVIF_PTZ_GotoPreset(2, ref common, _ONVIF_PTZ_GOTOPRESET);
                                //Log.Debug("巡视点执行4" + ret.ToString());
                            }
                        }
                        _bPtrsControlTour = false;
                    }

                }
            }
            catch (System.Exception ex)
            {

            }
        }

        /// <summary>
        /// 防区目标跟踪线程-------------内存增加速度60KB/S
        /// </summary>
        internal void trackThread()
        {

            bool bAlarm;

            _trackTime = DateTime.Now.AddSeconds(-100);
            _currentTarget = null;

            while (_bTaskContinue)
            {
                try
                {
                    _targetList.CheckPathOvertime();
                    newAvailableCount = _targetList.CombineTargets();

                    bAlarm = newAvailableCount != 0;    //判断是否生成了有效目标
                    if (this.IsAlarmInHand)                      //防区本来就在报警
                        bAlarm = true;

                    if (bAlarm)
                    {
                        //保存视频
                        this.ExecuteAlarmData();
                    }
                    trackTargetPath();

                }
                catch (System.Exception ex)
                {
                    //Log.Error(ex.ToString());
                }

                Thread.Sleep(TrackInterval);  //控制球机的时间间隔为200毫秒
            }
        }

        /// <summary>
        /// 球机的方位角
        /// </summary>
        public float cameraAngle;

        /// <summary>
        /// 球机当前监控距离
        /// </summary>
        public float cameraDistance = 1f;

        /// <summary>
        /// 球机视场大小
        /// </summary>
        public float cameraSight;

        /// <summary>
        /// 跟踪目标运动速度，小于0表示没有目标
        /// </summary>
        public float cameraTargetSpeed = -1;





        #endregion



        public string SearchLightIP
        {
            get { return _searchLightIp; }
            set { _searchLightIp = value; }
        }
        string _searchLightIp;

        public string angle
        {
            get { return _angle; }
            set { _angle = value; }
        }
        string _angle;

        public string Longitude
        {
            get { return _longitude; }
            set { _longitude = value; }
        }
        string _longitude;

        public string Latitude
        {
            get { return _latitude; }
            set { _latitude = value; }
        }
        string _latitude;
    }
}
